package com.esunny.online.controller;

import com.esunny.online.domain.dto.ResourceQuery;
import com.esunny.online.domain.dto.ReturnStructure;
import com.esunny.online.domain.entity.User;
import com.esunny.online.service.ResourceService;
import com.esunny.online.util.ConstantUtil;
import com.esunny.online.util.HostHolder;
import com.esunny.online.util.UUIDUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author ：李先生
 * @date ：Created in 2020/7/16 15:21
 * @description： 与资源相关的控制器
 * @modified By：
 * @version: $
 */
@Api(value = "资源请求控制器")
@Controller
@RequestMapping("/resource")
public class ResourceController {

    /**
     * 域名
     */
    @Value("${online.path.domain}")
    private String domain;

    /**
     * 核心路径
     */
    @Value("${server.servlet.context-path}")
    private String contextPath;
    /**
     * 文件上传路径
     */
    @Value("${online.path.upload}")
    private String uploadPath;

    /**
     * resourceService
     */
    @Resource
    private ResourceService resourceService;

    @Resource
    private HostHolder hostHolder;

    /**
     * 日志
     */
    private Logger logger = LoggerFactory.getLogger(ResourceController.class);

    /**
     * 请求上传文件
     *
     * @param file 文件
     * @return JSON
     */
    @ApiOperation(value = "上传文件接口")
    @ApiImplicitParam(paramType = "body", name = "file", value = "文件", required = true, dataType = "MultipartFile")
    @ApiResponse(code = 400, message = "参数错误", response = ReturnStructure.class)
    @PostMapping("/upload")
    @ResponseBody
    @CrossOrigin
    public ReturnStructure uploadFile(MultipartFile file) {
        String method = "/uploadFile：";

        if (file == null) {
            logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误，文件为空");
            return new ReturnStructure(400, "请求错误，文件为空");
        } else {
            com.esunny.online.domain.entity.Resource res = new com.esunny.online.domain.entity.Resource();
            //获取文件名
            String filename = file.getOriginalFilename();
            //获取文件后缀
            String suffix = "";
            if (null != filename) {
                suffix = filename.substring(filename.lastIndexOf("."));
            }
            if (StringUtils.isBlank(suffix)) {
                logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "文件格式错误");
                return new ReturnStructure(400, "文件格式错误");
            }
            //获取请求user
            User user = hostHolder.getUser();
            System.out.println(user);
            if (user == null) {
                return new ReturnStructure(400, "上传文件失败!");
            }
            //生成随机文件名
            String saveName = UUIDUtil.generateUUID() + suffix;
            //文件存放路径
            File dest = new File(uploadPath + File.separator + saveName);
            try {
                file.transferTo(dest);
            } catch (IOException e) {
                logger.error("上传文件失败，" + e.getMessage(), e);
                return new ReturnStructure(400, "上传文件失败,服务器异常!");
            }
            res.setName(filename);
            //路径
            String addr = domain + contextPath + "/" + saveName;
            res.setAddr(addr);
            //文件后缀 去掉.
            res.setType(suffix.substring(1));
            res.setCreateTime(new Date());
            res.setUserId(user.getId());
            res.setAuthor(user.getUsername());
            int row = resourceService.upload(res);
            if (row == 0) {
                logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "文件上传失败，服务器异常！");
                return new ReturnStructure(400, "文件上传失败，服务器异常！");
            }

            Map<String, Object> map = new HashMap<>(5);
            map.put("id", res.getId());
            return new ReturnStructure(200, "文件上传成功", map);

        }
    }

    /**
     * 请求下载文件
     *
     * @param fileId   文件id
     * @param response 响应
     */
    @ApiOperation(value = "下载/播放文件接口", notes = "基于文件Id下载/播放文件")
    @ApiImplicitParam(paramType = "path", name = "fileId", value = "文件ID", required = true, dataType = "Integer")
    @ApiResponse(code = 400, message = "请求失败", response = ReturnStructure.class)
    @GetMapping({"/download/{fileId}", "/display/{fileId}"})
    @CrossOrigin
    public ReturnStructure downloadFile(@PathVariable("fileId") int fileId, HttpServletResponse response) {

        //根据fileId查询Resource
        com.esunny.online.domain.entity.Resource resource = resourceService.queryById(fileId);
        //设置进度条可拉
        response.setHeader("Accept-Ranges", "bytes");
        response.setHeader("Content-Range", String.valueOf(10000 - 1));
        //设置response类型
        String suffix = resource.getType();
        //设置返回内容类型，根据需要进行扩展
        switch (suffix) {

            case ConstantUtil.RESOURCE_TYPE_PNG:
            case ConstantUtil.RESOURCE_TYPE_JPG:
            case ConstantUtil.RESOURCE_TYPE_GIF:
                response.setContentType("image/" + suffix);
                break;
            case ConstantUtil.RESOURCE_TYPE_MP4:
                response.setContentType("video/" + suffix);
                break;
            case ConstantUtil.RESOURCE_TYPE_MP3:
                response.setContentType("audio/mpeg");
                break;
            case ConstantUtil.RESOURCE_TYPE_ZIP:
            case ConstantUtil.RESOURCE_TYPE_PDF:
                response.setContentType("audio/" + suffix);
                break;
            case ConstantUtil.RESOURCE_TYPE_PPT:
                response.setContentType("application/vnd.ms-powerpoint");
                break;
            default:
                break;

        }

        //文件地址 = 存放地址+Resource的addr后半段
        String fileAddr = resource.getAddr();
        String[] splits = fileAddr.split("/");
        String saveAddr = uploadPath + File.separator + splits[splits.length - 1];

        //标志位
        //读取文件并通过response返回
        try (FileInputStream fis = new FileInputStream(saveAddr)) {
            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int b;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
            os.close();
        } catch (IOException e) {
            logger.error("下载文件失败" + e.getMessage(), e);
            return new ReturnStructure(400, "下载文件失败");
        }

        return new ReturnStructure(200, "下载文件成功");


    }

    /**
     * 根据文件Id查询文件信息
     *
     * @param fileId 文件Id
     * @return JSON
     */
    @ApiOperation(value = "查询数据接口", notes = "基于Id查询数据")
    @ApiImplicitParam(paramType = "path", name = "fileId", value = "文件ID", required = true, dataType = "Integer")
    @ApiResponse(code = 400, message = "请求失败", response = ReturnStructure.class)
    @GetMapping("/query/{fileId}")
    @ResponseBody
    @CrossOrigin
    public ReturnStructure queryById(@PathVariable("fileId") int fileId) {

        com.esunny.online.domain.entity.Resource resource = resourceService.queryById(fileId);
        if (resource == null) {
            return new ReturnStructure(400, "请求错误");
        } else {
            Map<String, Object> map = new HashMap<>(5);
            map.put("resource", resource);
            return new ReturnStructure(200, "查询成功", map);
        }

    }

    /**
     * 查询resource数据总数
     *
     * @return JSON
     */
    @ApiOperation(value = "查询数据总数接口")
    @ApiResponse(code = 400, message = "请求失败", response = ReturnStructure.class)
    @GetMapping("/queryCount")
    @ResponseBody
    @CrossOrigin
    public ReturnStructure queryCount() {
        int count = resourceService.queryCount();
        Map<String, Object> map = new HashMap<>(5);
        map.put("count", count);
        return new ReturnStructure(200, "请求成功", map);
    }


    /**
     * 查询资源文件列表
     *
     * @param resourceQuery 数据
     * @return JSON
     */
    @ApiOperation(value = "分页查询接口", notes = "基于当前页和每页数量进行分页查询")
    @ApiImplicitParam(paramType = "body", name = "resourceQuery", value = "ResourceQuery解析传入JSON", required = true, dataType = "ResourceQuery")
    @ApiResponse(code = 400, message = "请求失败", response = ReturnStructure.class)
    @PostMapping("/queryList")
    @ResponseBody
    @CrossOrigin
    public ReturnStructure queryList(@RequestBody ResourceQuery resourceQuery) {
        String method = "/queryList：";
        if (resourceQuery == null) {

            logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
            return new ReturnStructure(400, "请求错误");

        } else if (resourceQuery.getCurrentPage() == 0 || resourceQuery.getPageSize() == 0) {

            logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
            return new ReturnStructure(400, "请求错误");

        } else {
            String key = "resourceList";
            Map<String, Object> data = resourceService.queryByLimit(resourceQuery);
            if (data == null || data.isEmpty() || data.get(key) == null) {

                logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
                return new ReturnStructure(400, "请求错误");

            } else {
                return new ReturnStructure(200, "请求成功", data);
            }

        }
    }

    /**
     * 请求删除资源
     *
     * @param map 数据
     * @return JSON
     */
    @ApiOperation(value = "删除接口", notes = "根据传入Id删除资源")
    @ApiImplicitParam(paramType = "body", name = "map", value = "Map形式结合注解解析传入JSON", required = true, dataType = "Map")
    @ApiResponse(code = 400, message = "请求失败", response = ReturnStructure.class)
    @PostMapping("/del")
    @ResponseBody
    @CrossOrigin
    public ReturnStructure del(@RequestBody Map<String, Object> map) {
        String key = "id";
        String method = "/del：";
        if (map == null || map.isEmpty()) {
            logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
            return new ReturnStructure(400, "请求错误");
        } else if (map.get(key) == null) {
            logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
            return new ReturnStructure(400, "请求错误");
        } else {
            int row = resourceService.delete(map);

            if (row == 0) {
                logger.warn(ConstantUtil.LOGGER_CONTROLLER_RESOURCE + method + "请求错误");
                return new ReturnStructure(400, "请求错误");
            } else {
                return new ReturnStructure(200, "操作成功");
            }
        }

    }

}
